package cn.sfrog.project.biz.admin.service.impl;

import cn.sfrog.common.constant.ConfigConstants;
import cn.sfrog.common.core.domain.entity.SysUser;
import cn.sfrog.common.core.domain.model.LoginUser;
import cn.sfrog.common.core.redis.RedisCache;
import cn.sfrog.common.exception.ApiException;
import cn.sfrog.common.utils.DateUtils;
import cn.sfrog.common.utils.SecurityUtils;
import cn.sfrog.common.utils.StringUtils;
import cn.sfrog.framework.web.service.TokenService;
import cn.sfrog.project.biz.admin.domain.*;
import cn.sfrog.project.biz.admin.domain.vo.BizStudyProjectFormVO;
import cn.sfrog.project.biz.admin.domain.vo.BizStudyProjectMemberResultVO;
import cn.sfrog.project.biz.admin.domain.vo.BizStudyProjectQueryVO;
import cn.sfrog.project.biz.admin.domain.vo.BizStudyProjectVO;
import cn.sfrog.project.biz.admin.enums.BizUserTradeTypeEnum;
import cn.sfrog.project.biz.admin.mapper.BizStudyProjectMapper;
import cn.sfrog.project.biz.admin.mapper.BizStudyProjectMemberMapper;
import cn.sfrog.project.biz.admin.mapper.BizStudyProjectSponsorMapper;
import cn.sfrog.project.biz.admin.service.IBizStudyOrderService;
import cn.sfrog.project.biz.admin.service.IBizStudyProjectService;
import cn.sfrog.project.biz.admin.service.IBizStudyProjectSponsorService;
import cn.sfrog.project.biz.admin.service.IBizUserTradeRecordService;
import cn.sfrog.project.biz.web.vo.study.*;
import cn.sfrog.system.domain.vo.BizStatusChangeVO;
import cn.sfrog.system.mapper.SysUserMapper;
import cn.sfrog.system.service.ISysConfigService;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * 学研项目Service业务层处理
 */
@Service
public class BizStudyProjectServiceImpl extends ServiceImpl<BizStudyProjectMapper, BizStudyProject> implements IBizStudyProjectService {
    @Resource
    private BizStudyProjectMapper bizStudyProjectMapper;
    @Resource
    private BizStudyProjectMemberMapper studyProjectMemberMapper;
    @Resource
    private BizStudyProjectSponsorMapper bizStudyProjectSponsorMapper;
    @Autowired
    private IBizStudyProjectSponsorService bizStudyProjectSponsorService;
    @Resource
    private SysUserMapper sysUserMapper;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private IBizUserTradeRecordService bizUserTradeRecordService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private IBizStudyOrderService bizStudyOrderService;
    @Autowired
    private ISysConfigService sysConfigService;

    /**
     * 查询学研项目
     *
     * @param id 学研项目主键
     * @return 学研项目
     */
    @Override
    public BizStudyProjectVO selectBizStudyProjectById(Long id) {
        BizStudyProjectVO bizStudyProjectVO = bizStudyProjectMapper.selectBizStudyProjectById(id);
        if(StringUtils.isNotBlank(bizStudyProjectVO.getImages())){
            List<String> imageList = JSONObject.parseArray(bizStudyProjectVO.getImages(), String.class);
            bizStudyProjectVO.setImageList(imageList);
        }
        List<Date> dateList = new ArrayList<>();
        dateList.add(0,bizStudyProjectVO.getProjectStartTime());
        dateList.add(1,bizStudyProjectVO.getProjectEndTime());
        bizStudyProjectVO.setDateValue(dateList);
        //查项目成员
        List<BizStudyProjectMemberResultVO> resultVOList = studyProjectMemberMapper.selectProjectMemberListByProjectId(id);
        bizStudyProjectVO.setDoctorList(resultVOList);
        return bizStudyProjectVO;
    }

    /**
     * 查询学研项目列表
     *
     * @param query 学研项目
     * @return 学研项目
     */
    @Override
    public List<BizStudyProjectVO> selectBizStudyProjectList(BizStudyProjectQueryVO query) {
        if(query.getDateValue() != null){
            query.setStartTime(query.getDateValue()[0] + " 00:00:00");
            query.setEndTime(query.getDateValue()[1] + " 23:59:59");
        }
        return bizStudyProjectMapper.selectBizStudyProjectList(query);
    }

    /**
     * 新增学研项目
     *
     * @param form 学研项目
     * @return 结果
     */
    @Transactional(rollbackFor = Throwable.class)
    @Override
    public boolean insertBizStudyProject(BizStudyProjectFormVO form) {
        BizStudyProject bizStudyProject = new BizStudyProject();
        BeanUtils.copyProperties(form, bizStudyProject);
        Date startTime = form.getDateValue().get(0);
        Date endTime = form.getDateValue().get(1);
        bizStudyProject.setProjectStartTime(startTime);
        bizStudyProject.setProjectEndTime(endTime);
        Date nowDate = DateUtils.getNowDate();
        if(form.getImageArr() != null){
            bizStudyProject.setImages(JSONObject.toJSONString(form.getImageArr()));
        }
        if(nowDate.compareTo(startTime) < 0){
            //未开始
            bizStudyProject.setProjectStatus(BizStudyProject.NOT_START_STATUS);
        }
        if(nowDate.compareTo(endTime) > 0){
            //已结束
            bizStudyProject.setProjectStatus(BizStudyProject.OVER_STATUS);
        }
        if(nowDate.compareTo(startTime) > 0 && nowDate.compareTo(endTime) < 0){
            //进行中
            bizStudyProject.setProjectStatus(BizStudyProject.PROCESSING_STATUS);
        }
        bizStudyProject.setMemberCount(form.getDoctorList().size());
        bizStudyProject.setCreateTime(new Date());
        bizStudyProject.setCreateBy(SecurityUtils.getUsername());
        bizStudyProject.setUpdateTime(new Date());
        bizStudyProject.setUpdateBy(SecurityUtils.getUsername());
        boolean insert = bizStudyProject.insert();
        if(insert){
            List<BizStudyProjectFormVO.ProjectMember> doctorList = form.getDoctorList();
            for (BizStudyProjectFormVO.ProjectMember member:doctorList) {
                BizStudyProjectMember projectMember = new BizStudyProjectMember();
                projectMember.setProjectId(bizStudyProject.getId());
                projectMember.setUserId(member.getUserId());
                projectMember.setCreateTime(new Date());
                projectMember.setCreateBy(SecurityUtils.getUsername());
                projectMember.setUpdateTime(new Date());
                projectMember.setUpdateBy(SecurityUtils.getUsername());
                projectMember.insert();
            }
        }
        return insert;
    }

    /**
     * 修改学研项目
     *
     * @param form 学研项目
     * @return 结果
     */
    @Transactional(rollbackFor = Throwable.class)
    @Override
    public boolean updateBizStudyProject(BizStudyProjectFormVO form) {
        BizStudyProject bizStudyProject = new BizStudyProject();
        BeanUtils.copyProperties(form, bizStudyProject);
        Date startTime = form.getDateValue().get(0);
        Date endTime = form.getDateValue().get(1);
        bizStudyProject.setProjectStartTime(startTime);
        bizStudyProject.setProjectEndTime(endTime);
        Date nowDate = DateUtils.getNowDate();
        if(form.getImageArr() != null){
            bizStudyProject.setImages(JSONObject.toJSONString(form.getImageArr()));
        }
        if(nowDate.compareTo(startTime) < 0){
            //未开始
            bizStudyProject.setProjectStatus(BizStudyProject.NOT_START_STATUS);
        }
        if(nowDate.compareTo(endTime) > 0){
            //已结束
            bizStudyProject.setProjectStatus(BizStudyProject.OVER_STATUS);
        }
        if(nowDate.compareTo(startTime) > 0 && nowDate.compareTo(endTime) < 0){
            //进行中
            bizStudyProject.setProjectStatus(BizStudyProject.PROCESSING_STATUS);
        }
        bizStudyProject.setMemberCount(form.getDoctorList().size());

        bizStudyProject.setUpdateTime(new Date());
        bizStudyProject.setUpdateBy(SecurityUtils.getUsername());
        boolean flag = bizStudyProject.updateById();
        if(flag){
            //先把原来的删掉
            LambdaQueryWrapper<BizStudyProjectMember> lambdaQueryWrapper = new LambdaQueryWrapper<BizStudyProjectMember>()
                    .eq(BizStudyProjectMember::getProjectId,form.getId());
            BizStudyProjectMember.DAO.delete(lambdaQueryWrapper);
            List<BizStudyProjectFormVO.ProjectMember> doctorList = form.getDoctorList();
            for (BizStudyProjectFormVO.ProjectMember member:doctorList) {
                BizStudyProjectMember projectMember = new BizStudyProjectMember();
                projectMember.setProjectId(bizStudyProject.getId());
                projectMember.setUserId(member.getUserId());
                projectMember.setCreateTime(new Date());
                projectMember.setCreateBy(SecurityUtils.getUsername());
                projectMember.setUpdateTime(new Date());
                projectMember.setUpdateBy(SecurityUtils.getUsername());
                projectMember.insert();
            }
        }
        return flag;
    }

    /**
     * 批量删除学研项目
     *
     * @param ids 需要删除的学研项目主键
     * @return 结果
     */
    @Transactional(rollbackFor = Throwable.class)
    @Override
    public boolean deleteBizStudyProjectByIds(Long[] ids) {
            return BizStudyProject.DAO.delete(Wrappers.lambdaQuery(BizStudyProject.class).in(BizStudyProject::getId, (Object[]) ids));
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public boolean changeStatus(BizStatusChangeVO vo) {
        //return BizStudyProject.DAO.update(Wrappers.lambdaUpdate(BizStudyProject.class).in(BizStudyProject::getId, (Object[]) vo.getIds()).set(BizStudyProject::getStatus, vo.getStatus()));
        return true;
    }

    @Override
    public int cancel(BizStudyProjectFormVO form) {
        LambdaUpdateWrapper<BizStudyProject> updateWrapper = new LambdaUpdateWrapper<BizStudyProject>()
                .eq(BizStudyProject::getId,form.getId())
                .set(BizStudyProject::getProjectStatus,form.getProjectStatus())
                .set(BizStudyProject::getUpdateBy,SecurityUtils.getUsername())
                .set(BizStudyProject::getUpdateTime,DateUtils.getNowDate());
        return BizStudyProject.DAO.update(updateWrapper) ? 1 : 0;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public int audit(BizStudyProjectFormVO form) {
        BizStudyProject bizStudyProject = BizStudyProject.DAO.selectById(form.getId());
        bizStudyProject.setAllocation(form.getAllocation());
        bizStudyProject.setAuditStatus(BizStudyProject.AUDIT_STATUS_SUCCESS);
        boolean flag  = bizStudyProject.updateById();
        if(flag){
            List<BizStudyProjectFormVO.ProjectMember> doctorList = form.getDoctorList();
            for (BizStudyProjectFormVO.ProjectMember doctor:doctorList) {
                BizStudyProjectMember projectMember = new BizStudyProjectMember();
                projectMember.setId(doctor.getId());
                projectMember.setAllocation(form.getAllocation());
                projectMember.setDistributeScale(doctor.getDistributeScale());
                projectMember.updateById();
                //查询当前医生有没有绑定到登录用户的医生上
                LambdaQueryWrapper<BizUserAccount> queryWrapper = new LambdaQueryWrapper<BizUserAccount>()
                        .eq(BizUserAccount::getUserId,doctor.getUserId());
                BizUserAccount bizUserAccount = BizUserAccount.DAO.selectOne(queryWrapper);
                SysUser sysUser = new SysUser();
                sysUser.setUserId(doctor.getUserId());
                BigDecimal gainMoney  = BigDecimal.ZERO;
                if(BizStudyProject.ALLOCATION_AMOUNT.equals(form.getAllocation())){
                    //按金额分配
                    gainMoney = doctor.getDistributeScale();
                    bizUserAccount.setCommissionAmount(bizUserAccount.getCommissionAmount().add(gainMoney));
                }else if(BizStudyProject.ALLOCATION_SCALE.equals(form.getAllocation())){
                    //募集金额
                    BigDecimal raisedAmount = bizStudyProject.getRaisedAmount();
                    BigDecimal scale = doctor.getDistributeScale().divide(new BigDecimal(100));
                    gainMoney = (raisedAmount.multiply(scale)).setScale(0);
                    bizUserAccount.setCommissionAmount(bizUserAccount.getCommissionAmount().add(gainMoney));
                }
                bizUserAccount.updateById();
                sysUser.setEscortBeanCount(bizUserAccount.getAccountBalance().add(bizUserAccount.getGiveAwayAmount()).add(bizUserAccount.getCommissionAmount()));
                sysUserMapper.updateUser(sysUser);
                //记录用户交易记录
                bizUserTradeRecordService.saveUserTradeRecord(doctor.getUserId(),gainMoney, BizUserTradeTypeEnum.STUDY_DISTRIBUTION.getCode(),redisCache.buildStudyOrderDistributeSerialNumber(),bizStudyProject.getName());
            }
        }
        return flag ? 1 : 0;
    }

    @Override
    public int finish(Long id) {
        BizStudyProject bizStudyProject = BizStudyProject.DAO.selectById(id);
        bizStudyProject.setRealEndTime(DateUtils.getNowDate());
        bizStudyProject.setProjectStatus(BizStudyProject.OVER_STATUS);
        return bizStudyProject.updateById() ? 1 : 0;
    }

    @Override
    public List<AppStudyProjectResultVO> selectAppStudyProjectList(AppStudyProjectQueryVO queryVO) {
        return bizStudyProjectMapper.selectAppStudyProjectList(queryVO);
    }

    @Override
    public AppStudyProjectDetailResultVO selectAppStudyProjectDetail(Long id) {
        AppStudyProjectDetailResultVO resultVO = bizStudyProjectMapper.selectAppStudyProjectDetail(id);
        if(StringUtils.isNotNull(resultVO)){
            resultVO.setProjectStatus(BizStudyProject.PROCESSING_STATUS);
            if(StringUtils.isNotBlank(resultVO.getImages())){
                List<String> imageList = JSONObject.parseArray(resultVO.getImages(), String.class);
                resultVO.setImageList(imageList);
            }
            //项目成员
            List<AppStudyProjectMemberVO> memberVOList =  studyProjectMemberMapper.selectAppProjectMemberList(id);
            resultVO.setMemberList(memberVOList);
            //项目捐赠记录
            List<AppStudyProjectSponsorVO> sponsorList =  bizStudyProjectSponsorMapper.selectAppProjectSponsorList(id);
            resultVO.setSponsorList(sponsorList);
        }

        return resultVO;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Boolean projectDonate(AppProjectDonateFormVO formVO) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser user =loginUser.getUser();
        BizStudyProject project = BizStudyProject.DAO.selectById(formVO.getProjectId());
        if(project.getProjectEndTime().before(DateUtils.getNowDate()) || BizStudyProject.OVER_STATUS.equals(project.getProjectStatus())){
            throw new ApiException("该项目已经结束!");
        }
        String donateLimit = sysConfigService.selectConfigByKey(ConfigConstants.DONATE_LIMIT);
        if(formVO.getDonateAmount().compareTo(new BigDecimal(donateLimit)) == 1){
            throw new ApiException("项目捐助单次最大陪护豆为"+donateLimit+"颗,您已超出最大数量。");
        }

        //项目金额
        BigDecimal price = project.getPrice();
        //募捐金额
        BigDecimal raisedAmount = project.getRaisedAmount();
        if(price.compareTo(raisedAmount) == 0){
            throw new ApiException("项目募捐已经完成，暂时无法捐赠。");
        }
        //还需要的金额
        BigDecimal subAmount = price.subtract(raisedAmount);
        if(formVO.getDonateAmount().compareTo(subAmount) == 1){
            BigDecimal subAmount2 = subAmount.setScale(0);
            throw new ApiException("您只需捐助"+subAmount2+"颗陪护豆即可完成项目募捐了。");
        }
        LambdaQueryWrapper<BizUserAccount> lambdaQueryWrapper = new LambdaQueryWrapper<BizUserAccount>()
                .eq(BizUserAccount::getUserId,user.getUserId());
        BizUserAccount bizUserAccount = BizUserAccount.DAO.selectOne(lambdaQueryWrapper);
        //账户可用余额
        BigDecimal ableAmount = bizUserAccount.getAccountBalance();
        //赠送金额
        BigDecimal giveAwayAmount = bizUserAccount.getGiveAwayAmount();
        //可用的代理提成金额
        BigDecimal commissionAmount = bizUserAccount.getCommissionAmount().subtract(bizUserAccount.getFreezeAmount());
        if(formVO.getDonateAmount().compareTo((ableAmount.add(giveAwayAmount)).add(commissionAmount)) == 1){
            throw new ApiException("捐助金额超出您的账户余额,请充值账户余额!");
        }
        //捐助金额
        BigDecimal donateAmount = formVO.getDonateAmount();
        //生成学研订单
        BizStudyOrder studyOrder =  bizStudyOrderService.createStudyOrder(user.getUserId(),formVO.getDonateAmount(),formVO.getProjectId(),project.getHospitalId());
        //生成捐助记录
        BizStudyProjectSponsor sponsor = bizStudyProjectSponsorService.createStudyProjectSponsor(formVO,user,studyOrder.getStudyOrderSn());
        boolean insert = sponsor.insert();
        if(insert){
            //更新用户账户信息
            // 1.如果支付金额 < 账户可用余额 则直接扣减账户余额
            if(donateAmount.compareTo(ableAmount) < 1){
                bizUserAccount.setAccountBalance(bizUserAccount.getAccountBalance().subtract(donateAmount));
            }else if((donateAmount.compareTo(ableAmount) == 1) && (donateAmount.compareTo((ableAmount.add(commissionAmount)))) < 1 ) {
                //2.（支付金额 > 账户可用余额） 并且 （支付金额 < 账户可用余额 + 代理提成金额）
                bizUserAccount.setAccountBalance(bizUserAccount.getAccountBalance().subtract(ableAmount));
                BigDecimal subGiveAwayAmount = donateAmount.subtract(ableAmount);
                bizUserAccount.setCommissionAmount(bizUserAccount.getCommissionAmount().subtract(subGiveAwayAmount));
            }else{
                // 3.（支付金额 > 账户可用余额） && （支付金额 > 账户可用余额 + 代理分成金额） && （支付金额 < 账户可用余额 + 代理分成金额 + 充值赠送金额）
                bizUserAccount.setAccountBalance(bizUserAccount.getAccountBalance().subtract(ableAmount));
                bizUserAccount.setCommissionAmount(bizUserAccount.getCommissionAmount().subtract(commissionAmount));
                BigDecimal subGiveAwayAmount = donateAmount.subtract((ableAmount.add(commissionAmount)));
                bizUserAccount.setGiveAwayAmount(bizUserAccount.getGiveAwayAmount().subtract(subGiveAwayAmount));
            }
            bizUserAccount.setConsumeAmount(bizUserAccount.getConsumeAmount().add(donateAmount));
            bizUserAccount.updateById();
            //更新用户的陪护豆余额
            user.setEscortBeanCount(bizUserAccount.getAccountBalance().add(bizUserAccount.getGiveAwayAmount()).add(bizUserAccount.getCommissionAmount()));
            sysUserMapper.updateUser(user);
            loginUser.setUser(user);
            tokenService.refreshToken(loginUser);

            //记录用户交易记录
            bizUserTradeRecordService.saveUserTradeRecord(user.getUserId(),donateAmount.negate(), BizUserTradeTypeEnum.DONATE.getCode(),studyOrder.getStudyOrderSn(),"捐助/"+project.getName());
        }

        //更新项目的进度和募集金额
        project.setRaisedAmount((project.getRaisedAmount() == null ? BigDecimal.ZERO: project.getRaisedAmount()).add(formVO.getDonateAmount()));
        BigDecimal schedule = ((project.getRaisedAmount().divide(project.getPrice(), 2, BigDecimal.ROUND_HALF_UP))).setScale(2, BigDecimal.ROUND_DOWN).multiply(BigDecimal.valueOf(100));
        if(schedule.compareTo(BigDecimal.valueOf(100)) == 1){
            schedule = BigDecimal.valueOf(100);
        }
        project.setSchedule(schedule);
        project.updateById();
        return insert;
    }

    @Override
    public List<AppStudyProjectResultVO> selectDoctorStudyProjectList(AppStudyProjectQueryVO queryVO) {
        return bizStudyProjectMapper.selectDoctorStudyProjectList(queryVO);
    }

    public static void main(String[] args) {
        BigDecimal  bigDecimal =  BigDecimal.valueOf(1).divide(BigDecimal.valueOf(30000),2,BigDecimal.ROUND_HALF_UP).setScale(2,BigDecimal.ROUND_UP);
       // BigDecimal bigDecimal = BigDecimal.valueOf(1).divide(BigDecimal.valueOf(30000)).multiply(BigDecimal.valueOf(100)).setScale(1, BigDecimal.ROUND_DOWN);
        System.out.println(bigDecimal);
    }
}
